import yaml
import re
import numpy as np
from pathlib import Path
from typing import Dict
import librosa

# 导入项目模块
from src.fingerprinting.processor import Processor
from src.fingerprinting.hashing import Hasher
from src.utils import PROCESSOR_RESULTS_PATH

def run_diagnostic_comparison(
        original_path: Path,
        sample_path: Path,
        sample_start_sec: int,
        sample_duration_sec: int,
        config: Dict
) -> Dict:
    """
    对一个音频文件的时间切片和另一个样本文件进行详细的指纹对比，并生成可视化图表。
    """
    processor = Processor(config)
    hasher = Hasher(config['hashing'])
    results = {}

    # 为本次诊断创建一个唯一的子目录，防止文件名冲突
    diag_output_dir = PROCESSOR_RESULTS_PATH / f"diag_{original_path.stem}_vs_{sample_path.stem}"
    diag_output_dir.mkdir(parents=True, exist_ok=True)

    try:
        # --- 1. 处理测试样本 ---
        y_sample, _ = librosa.load(str(sample_path), sr=processor.sr, mono=True)
        y_sample_filtered = processor._highpass_filter(y_sample)
        sample_spec, sample_freqs, sample_times = processor._compute_spectrogram(y_sample_filtered)
        sample_peaks = processor._find_peaks(sample_spec, sample_freqs, sample_times)

        if not sample_peaks.any():
            return {'error': f"无法从样本 '{sample_path.name}' 中提取峰值点。"}

        # 保存样本的语谱图
        sample_spec_path = processor._save_spectrogram_plot(
            sample_spec, sample_peaks,
            diag_output_dir / "sample_spectrogram.png",
            f"样本语谱图 - {sample_path.name}"
        )

        sample_fingerprints = hasher.peaks_to_fingerprints(sample_peaks)
        sample_hashes = {fp[0] for fp in sample_fingerprints}
        results['sample'] = {
            'name': sample_path.name,
            'peaks': sample_peaks.tolist(),
            'fingerprints_count': len(sample_hashes),
            'spectrogram_url': Path(sample_spec_path).relative_to(PROCESSOR_RESULTS_PATH).as_posix()
        }

        # --- 2. 处理原曲并按时间切片 ---
        y_orig, _ = librosa.load(str(original_path), sr=processor.sr, mono=True)
        y_orig_filtered = processor._highpass_filter(y_orig)
        orig_spec, orig_freqs, orig_times = processor._compute_spectrogram(y_orig_filtered)

        # 根据时间窗口过滤原曲的峰值点
        time_end = sample_start_sec + sample_duration_sec
        all_original_peaks = processor._find_peaks(orig_spec, orig_freqs, orig_times)
        mask = (all_original_peaks[:, 0] >= sample_start_sec) & (all_original_peaks[:, 0] <= time_end)
        original_sliced_peaks = all_original_peaks[mask]

        if not original_sliced_peaks.any():
            return {'error': f"原曲在 {sample_start_sec}s-{time_end}s 时间段内没有峰值点。"}

        # 提取语谱图的时间切片
        start_frame = librosa.time_to_frames(sample_start_sec, sr=processor.sr, hop_length=processor.hop_length)
        end_frame = librosa.time_to_frames(time_end, sr=processor.sr, hop_length=processor.hop_length)
        orig_spec_sliced = orig_spec[:, start_frame:end_frame]

        # 调整峰值点的时间戳，使其从0开始，以便在切片后的语谱图上正确显示
        original_sliced_peaks_adjusted = original_sliced_peaks.copy()
        original_sliced_peaks_adjusted[:, 0] -= sample_start_sec

        # 保存原曲切片的语谱图
        orig_spec_path = processor._save_spectrogram_plot(
            orig_spec_sliced, original_sliced_peaks_adjusted,
            diag_output_dir / "original_slice_spectrogram.png",
            f"原曲切片语谱图 [{sample_start_sec}s-{time_end}s]"
        )

        original_fingerprints = hasher.peaks_to_fingerprints(original_sliced_peaks_adjusted)
        original_hashes = {fp[0] for fp in original_fingerprints}
        results['original'] = {
            'name': original_path.name + f" [{sample_start_sec}s-{time_end}s]",
            'peaks': original_sliced_peaks_adjusted.tolist(),
            'fingerprints_count': len(original_hashes),
            'spectrogram_url': Path(orig_spec_path).relative_to(PROCESSOR_RESULTS_PATH).as_posix()
        }

        # --- 3. 对比分析 ---
        matching_hashes = original_hashes.intersection(sample_hashes)
        num_matches = len(matching_hashes)
        overlap_percentage = (num_matches / len(sample_hashes)) * 100 if len(sample_hashes) > 0 else 0

        analysis_text = "✅ 高重合度" if overlap_percentage > 10 else "⚠️ 低重合度" if overlap_percentage > 0 else "❌ 无重合度"
        results['comparison'] = {
            'matches': num_matches, 'overlap': round(overlap_percentage, 2), 'analysis': analysis_text
        }

    except Exception as e:
        import traceback
        traceback.print_exc()
        return {'error': f"诊断过程中发生错误: {e}"}

    return results
